package com.dacool.http;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.dacool.config.Config;
import com.dacool.util.SignatureTool;

public class HttpTool {

	public static class Response {
		public String data;
		public int statusCode;
	}

	public static DefaultHttpClient httpClient;

	public static Response getRequest(String url,
			HashMap<String, Object> params, boolean saveCookies)
			throws ClientProtocolException, IOException, JSONException {

		StringBuilder sb = new StringBuilder(url);
		int index = url.indexOf("?");
		if (index > 0) {
			sb.append("&");
		} else {
			sb.append("?");
		}
		sb.append(SignatureTool.getSignedParams(params));
//		Log.d("test", "params:" + sb.toString());
		HttpGet get = new HttpGet(sb.toString());
		setCookie(get);
		DefaultHttpClient client = getClient();
		client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
				getUserAgent());
		HttpResponse httpResponse = client.execute(get);
		if (saveCookies) {
			List<Cookie> cookies = client.getCookieStore().getCookies();
			if (cookies.isEmpty()) {
				Log.i("test", "-------Cookie NONE---------");
			} else {
				for (int i = 0; i < cookies.size(); i++) {
					Cookie cookie = cookies.get(i);
//					Log.d("test",
//							"cookie " + cookie.getName() + ":"
//									+ cookie.getValue());
//					Log.d("test", "cookie" + cookie.toString());
//					Log.d("test", "cookie expire " + cookie.getExpiryDate());
					Config.sharedConfig().cookies.put(cookie.getName(),
							cookie.getValue());
					if (cookie.getExpiryDate() != null) {
						Config.sharedConfig().cookieExpireDate = cookie
								.getExpiryDate();
					}
				}
				Config.sharedConfig().save();
			}
		}
		int statusCode = httpResponse.getStatusLine().getStatusCode();
		if (statusCode == 302 || statusCode == 301) {
			Header[] hs = httpResponse.getHeaders("Location");
			String location = null;
			if (hs.length > 0) {
				location = hs[0].getValue();
			}
			Response response = new Response();
			response.statusCode = statusCode;
			response.data = location;
			return response;
		}

		String result = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
		Response response = new Response();
		response.statusCode = statusCode;
		response.data = result;
		return response;
	}

	private static void setCookie(HttpGet get) {
		StringBuilder sb = new StringBuilder();
		for (String key : Config.sharedConfig().cookies.keySet()) {
			sb.append(String.format("%s=\"%s\";", key,
					Config.sharedConfig().cookies.get(key)));
		}
		get.addHeader("Cookie", sb.toString());
//		Log.d("test", "get cookie:" + get.getFirstHeader("Cookie").getValue());
	}

	private static void setCookie(HttpPost post) {
		StringBuilder sb = new StringBuilder();
		for (String key : Config.sharedConfig().cookies.keySet()) {
			sb.append(String.format("%s=\"%s\";", key,
					Config.sharedConfig().cookies.get(key)));
		}
		post.addHeader("Cookie", sb.toString());
//		Log.d("test", "post cookie:" + post.getFirstHeader("Cookie").getValue());
	}

	public static JSONObject deleteRequest(String url, String username,
			String password) throws ClientProtocolException, IOException,
			JSONException {
		HttpDelete delete = new HttpDelete(url);
		httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
				getUserAgent());
		HttpResponse httpResponse = httpClient.execute(delete);
		int statusCode = httpResponse.getStatusLine().getStatusCode();
		if (statusCode == 200) {
			String result = EntityUtils.toString(httpResponse.getEntity(),
					"utf-8");
			return new JSONObject(result);
		} else {
			String result = EntityUtils.toString(httpResponse.getEntity(),
					"utf-8");
			JSONObject ret = new JSONObject(result);
			return getErrorJsonObject(ret, statusCode);
		}
	}

	private static DefaultHttpClient getClient() {
		// if (httpClient == null) {

		HttpParams httpParams = new BasicHttpParams();
		ConnManagerParams.setTimeout(httpParams, 10000);
		httpParams.setParameter("http.protocol.handle-redirects", false);
		HttpClientParams.setCookiePolicy(httpParams,
				CookiePolicy.BROWSER_COMPATIBILITY);
		HttpConnectionParams.setConnectionTimeout(httpParams, 8000);
		HttpConnectionParams.setSoTimeout(httpParams, 20000);
		DefaultHttpClient client = new DefaultHttpClient(httpParams);
		client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
				getUserAgent());
		// }
		return client;
	}

	public static Response postRequst(String url,
			HashMap<String, Object> params, boolean saveCookies)
			throws ParseException, IOException, JSONException {
		DefaultHttpClient client = getClient();
		HttpPost post = new HttpPost(url);
		post.setHeader(HTTP.CONTENT_TYPE,
				"application/x-www-form-urlencoded;charset=utf-8");
		setCookie(post);
		String signedParams = SignatureTool.getSignedParams(params);
//		Log.d("test", "signedParams:" + signedParams);
		post.setEntity(new StringEntity(signedParams, "utf-8"));
		HttpResponse httpResponse = client.execute(post);
		int statusCode = httpResponse.getStatusLine().getStatusCode();

		Response response = new Response();
		if (saveCookies) {
			List<Cookie> cookies = client.getCookieStore().getCookies();
			if (cookies.isEmpty()) {
				Log.i("test", "-------Cookie NONE---------");
			} else {
				for (int i = 0; i < cookies.size(); i++) {
					Cookie cookie = cookies.get(i);
					Config.sharedConfig().cookies.put(cookie.getName(),
							cookie.getValue());
//					Log.d("test",
//							"cookie " + cookie.getName() + ":"
//									+ cookie.getValue());
//					Log.d("test", "cookie" + cookie.toString());
//					Log.d("test", "cookie expire " + cookie.getExpiryDate());
					if (cookie.getExpiryDate() != null)
						Config.sharedConfig().cookieExpireDate = cookie
								.getExpiryDate();
				}
				Config.sharedConfig().save();
			}
		}
		if (statusCode == 302 || statusCode == 301) {
			Header[] hs = httpResponse.getHeaders("Location");
			String location = null;
			if (hs.length > 0) {
				location = hs[0].getValue();
			}
			response.statusCode = statusCode;
			response.data = location;
			return response;
		}

		String result = EntityUtils.toString(httpResponse.getEntity());
		response.data = result;
		response.statusCode = statusCode;
		return response;
	}

	public static JSONObject putRequst(String url, JSONObject jsonObject,
			String username, String password) throws ParseException,
			IOException, JSONException {
		HttpPut put = new HttpPut(url);
		httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
				getUserAgent());
		put.setHeader(HTTP.CONTENT_TYPE, "application/json");
		put.setEntity(new StringEntity(jsonObject.toString(), "utf-8"));
		HttpResponse httpResponse = httpClient.execute(put);
		int statusCode = httpResponse.getStatusLine().getStatusCode();
		if (statusCode == 201 || statusCode == 200) {
			String result = EntityUtils.toString(httpResponse.getEntity());
			return new JSONObject(result);
		} else {
			String result = EntityUtils.toString(httpResponse.getEntity());
			JSONObject ret = new JSONObject(result);
			return getErrorJsonObject(ret, statusCode);
		}
	}

	public static JSONObject getErrorJsonObject(JSONObject ret, int statusCode)
			throws JSONException {
		JSONObject errorRet = new JSONObject();
		// String errorMsg = ret.optString("err_msg");
		// int errorCode = ret.optInt("err_code");
		// errorRet.put("status", 0);
		// if (errorCode == 0) {
		// errorRet.put("err_code", statusCode);
		// } else {
		// errorRet.put("err_code", errorCode);
		// }
		// errorRet.put("err_msg", errorMsg);
		errorRet = ret;
		return errorRet;
	}

	private static String getUserAgent() {
		String ua = "android client 1.0";
		return ua;
	}
}
